package it.eng.area118.mdocommon.android.model;

import it.eng.area118.mdocommon.ModelContainer;
import it.eng.area118.mdocommon.android.util.AndroidApplicationContext;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 
 * @author Luigi
 * 
 *         I model utilizzati dalla realizzazione Android del ModelContainer
 *         devono implementare l'interfaccia Serializable
 * 
 * 
 */
public class AndroidModelContainer implements ModelContainer {

	private static ModelContainer INSTANCE;

	private static Object object = new Object();

	private Set<String> keys;

	private Map<String, List<ModelListener>> listenersMap;

	public AndroidModelContainer() {
		keys = new HashSet<String>();
		listenersMap = new ConcurrentHashMap<String, List<ModelListener>>();
	}

	public void putModel(String key, Object o) {
		putModel(key, o, false);
	}

	public void putModel(String key, Object o, boolean notify) {
		keys.add(key);
		AndroidApplicationContext.getInstance().putApplicationContextEntry(key,
				o);
		if (notify) {
			List<ModelListener> list = listenersMap.get(key);
			if (list != null && list.size() > 0) {
				for (ModelListener modelListener : list) {
					modelListener.update(o);
				}
			}
		}
	}

	@Override
	public void registerForModel(String modelKey, ModelListener listener) {
		List<ModelListener> list = listenersMap.get(modelKey);
		if (list == null) {
			list = new ArrayList<ModelListener>();
		}
		list.add(listener);
		listenersMap.put(modelKey, list);
	}

	@Override
	public void unregisterAllForModel(String modelKey) {
		List<ModelListener> list = listenersMap.get(modelKey);
		if (list != null) {
			list.clear();
		}
	}

	public synchronized static ModelContainer createInstance() {

		synchronized (object) {
			if (INSTANCE == null) {

				INSTANCE = new AndroidModelContainer();
			}

			return INSTANCE;
		}

	}

	public synchronized static ModelContainer getInstance() {
		// synchronized (object) {
		if (INSTANCE == null) {
			throw new NullPointerException(
					"ModelContainer instance never create... use createInstance first!");
		}
		return INSTANCE;
		// }

	}

	public synchronized static void destroyInstance() {
		synchronized (object) {
			INSTANCE = null;
		}
	}

	@Override
	public Object removeModel(String key) {
		return AndroidApplicationContext.getInstance()
				.removeApplicationContextEntry(key);
	}

	@Override
	public Object replaceModel(String key, Object newModel) {
		Object o = AndroidApplicationContext.getInstance()
				.getApplicationContextValue(key);
		AndroidApplicationContext.getInstance().putApplicationContextEntry(key,
				newModel);
		return o;
	}

	@Override
	public Object getModel(String key) {
		return AndroidApplicationContext.getInstance()
				.getApplicationContextValue(key);
	}

	@Override
	public Map<String, Object> getAllModels() {
		Map<String, Object> map = new HashMap<String, Object>();
		for (String key : keys) {
			map.put(key, getModel(key));
		}
		return map;
	}

}
